#include "spriteanimado.h"

#include <stdio.h>

#include "tinyxml/tinyxml.h"

namespace gge
{

SpriteAnimado::SpriteAnimado()
{
	Limpiar();
}


SpriteAnimado::~SpriteAnimado()
{
}

void SpriteAnimado::Limpiar()
{
	m_secuenciaActual=-1;
	m_siguienteSecuencia=-1;
	
	m_listaSecuencias.clear();
	m_reproduciendo=false;
	m_tiempo.Reset();
	m_ciclo=false;
	m_posicion.x=0;
	m_posicion.y=0;
	
	m_volteadoX = false;
	m_volteadoY = false;
	
	m_invertido=false;
	m_rotacion = 0;
}

void SpriteAnimado::Actualizar()
{
	bool actualiza=m_reproduciendo;

	if (m_secuenciaActual<0)
		return;
		
	float tiempo= m_tiempo.GetElapsedTime();

	if (m_listaSecuencias[m_secuenciaActual].duracion <= tiempo && m_reproduciendo)
	{
		if (m_ciclo )
		{
			m_tiempo.Reset();
			actualiza=true;
		}
		else if(m_siguienteSecuencia >= 0)
		{
			m_secuenciaActual=m_siguienteSecuencia;
			m_siguienteSecuencia =-1;
			
			m_tiempo.Reset();
			actualiza=true;
		}
		else
		{
			actualiza=false;
			m_reproduciendo=false;
		}
	}
		
	if (actualiza)
	{
		Secuencia * sec = &m_listaSecuencias[m_secuenciaActual];
		sec->frameActual = (int)( sec->listaFrames.size() * tiempo / sec->duracion );
		if (m_invertido)
		{
			sec->frameActual = (sec->listaFrames.size()-1) - sec->frameActual;
		}
		if (sec->frameActual >= sec->listaFrames.size())
			sec->frameActual = sec->listaFrames.size();
	}
	
	//m_ventana->Draw(sec->listaFrames[sec->frameActual]);
}

void SpriteAnimado::AgregarSecuencia(Secuencia sec)
{
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	
	while (itSec != m_listaSecuencias.end())
	{
		if (itSec->nombre.compare(sec.nombre)==0)
			break;
		itSec++;
	}
	
	if (itSec == m_listaSecuencias.end())
	{
		printf("actualizando posición: %s", sec.nombre.c_str());
		std::vector<sf::Sprite>::iterator itFrame = sec.listaFrames.begin();
		while (itFrame != sec.listaFrames.end())
		{
			itFrame->SetPosition(ObtenerPosicion());
			itFrame++;
		}
		
		m_listaSecuencias.push_back(sec);
		printf("Agregada secuencia: %s", sec.nombre.c_str());
	}
}

void SpriteAnimado::AgregarSecuencia(std::vector<sf::Sprite> lista, std::string nombre, float duracion)
{
	if (lista.size()>0)
	{
		std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
		
		while (itSec != m_listaSecuencias.end())
		{
			if (itSec->nombre.compare(nombre)==0)
				break;
			itSec++;
		}
		
		if (itSec == m_listaSecuencias.end())
		{
			Secuencia sec;
			sec.duracion=duracion;
			sec.nombre=nombre;
			for (int x=0; x<lista.size(); x++)
			{
				lista[x].SetPosition(ObtenerPosicion());
				lista[x].Rotate(m_rotacion);
				lista[x].FlipX(m_volteadoX);
				lista[x].FlipY(m_volteadoY);
				sec.listaFrames.push_back(lista[x]);
			}
			sec.frameActual=0;
			m_listaSecuencias.push_back(sec);
		}
	}
}

void SpriteAnimado::Animar(bool ciclo)
{
	m_reproduciendo=true;
	m_ciclo=ciclo;
	m_tiempo.Reset();
}

void SpriteAnimado::CambiarSecuencia(int indice)
{
	if (indice >=0 && indice < m_listaSecuencias.size() && indice != m_secuenciaActual)
	{
		m_listaSecuencias[m_secuenciaActual].frameActual=0;
		
		m_siguienteSecuencia=-1;
		m_secuenciaActual=indice;
		m_listaSecuencias[m_secuenciaActual].frameActual=0;
		m_tiempo.Reset();
		m_reproduciendo=true;
	}
}

void SpriteAnimado::CambiarSecuencia(std::string nombre)
{
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	int indice=0;
	while (itSec != m_listaSecuencias.end())
	{
		if (itSec->nombre.compare(nombre)==0)
			break;
		itSec++;
		indice++;
	}
	if (itSec != m_listaSecuencias.end() && indice!=m_secuenciaActual)
	{
		CambiarSecuencia(indice);
	}
}

bool SpriteAnimado::CrearDeArchivo(std::string xmlPath)
{
	bool res=false;
	TiXmlDocument doc(xmlPath.c_str());
	if (doc.LoadFile())
	{
		TiXmlHandle hDoc(&doc);

		TiXmlElement* pAnimElem=NULL;
		
		pAnimElem = hDoc.FirstChildElement("animacion").Element();
		if (pAnimElem)
		{
			m_listaSecuencias.clear();
			std::string path("");
			
			int pos=xmlPath.find_last_of('/');
			if (pos <0 ||pos>xmlPath.size())
				pos=xmlPath.find_last_of('\\');
				
			if (pos >=0 && pos<xmlPath.size())
				path=xmlPath.substr(0,pos+1);
			
			m_imageManager.add_resource_directory(path);
			
			TiXmlElement* pSecElem = pAnimElem->FirstChildElement("secuencia");
			
			while (pSecElem)
			{
				Secuencia sec;
				std::string nombre("");
				float duracion;
				//pSecElem->QueryStringAttribute("nombre",&nombre) ;
				nombre = pSecElem->Attribute("nombre");
				pSecElem->QueryFloatAttribute("duracion",&duracion);
				
				sec.nombre=nombre;
				sec.duracion=duracion;
				
				TiXmlElement* pFrameElem = pSecElem->FirstChildElement("cuadro");
				while (pFrameElem)
				{
					std::string fileName (pFrameElem->FirstChild()->Value());
					if (path.find(fileName)== std::string::npos)
						fileName.insert(0,path);
						
					sf::Image img;						
					if (img.LoadFromFile(fileName.c_str()))
					{
						printf("cargado: %s", fileName.c_str());
						
						sf::Sprite sprite(m_imageManager.get_image(fileName));
						sec.listaFrames.push_back(sprite);
					}
					pFrameElem = pFrameElem->NextSiblingElement("cuadro");
				}
								
				AgregarSecuencia(sec);						
				pSecElem = pSecElem->NextSiblingElement("secuencia");
			}
		}

	}
	return res;
}

void SpriteAnimado::Detener()
{
	m_reproduciendo=false;
}

Secuencia *SpriteAnimado::ObtenerSecuencia(int indice)
{
	if (indice < m_listaSecuencias.size())
		return &(m_listaSecuencias[indice]);
	else
		return NULL;
}

Secuencia *SpriteAnimado::ObtenerSecuencia(std::string nombre)
{
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	
	while (itSec != m_listaSecuencias.end())
	{
		if (itSec->nombre.compare(nombre)==0)
			break;
		itSec++;
	}
	
	if (itSec != m_listaSecuencias.end())
	{
		return &(*itSec);
	}
	else
	{
		return false;
	}
}

Secuencia *SpriteAnimado::SecuenciaActual()
{
	return &(m_listaSecuencias[m_secuenciaActual]);
}

bool SpriteAnimado::SecuenciaTerminada()
{
	if (m_listaSecuencias[m_secuenciaActual].duracion <= m_tiempo.GetElapsedTime())
		return true;
	else
		return false;
}

void SpriteAnimado::SiguienteSecuencia(int indice)
{
	if (indice >=0 && indice < m_listaSecuencias.size())
	{
		m_siguienteSecuencia=indice;
	}
}

void SpriteAnimado::SiguienteSecuencia(std::string nombre)
{
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	int indice=0;
	while (itSec != m_listaSecuencias.end())
	{
		if (itSec->nombre.compare(nombre)==0)
			break;
		itSec++;
		indice++;
	}
	
	if (itSec != m_listaSecuencias.end())
	{
		m_siguienteSecuencia = indice;
	}
}

float SpriteAnimado::Tiempo()
{
	return m_tiempo.GetElapsedTime();
}

void SpriteAnimado::CambiarPosicion(sf::Vector2f pos)
{
	m_posicion=pos;
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	while (itSec != m_listaSecuencias.end())
	{
		std::vector<sf::Sprite>::iterator itFrame = itSec->listaFrames.begin();
		while (itFrame != itSec->listaFrames.end())
		{
			itFrame->SetPosition(pos);
			itFrame++;
		}
		itSec++;
	}

}

sf::Vector2f SpriteAnimado::ObtenerPosicion()
{
	return m_posicion;
}

sf::Sprite SpriteAnimado::CuadroActual()
{
	sf::Sprite Res;
	if(m_secuenciaActual>=0 && m_secuenciaActual <m_listaSecuencias.size())
	{
		Secuencia sec = m_listaSecuencias[m_secuenciaActual];
		if (sec.frameActual>=0 && sec.frameActual < sec.listaFrames.size())
			Res= sec.listaFrames[sec.frameActual];
	}
	return Res;
}

void SpriteAnimado::Rotar(float angulo)
{
	m_rotacion=angulo;
	
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	while (itSec != m_listaSecuencias.end())
	{
		std::vector<sf::Sprite>::iterator itFrame = itSec->listaFrames.begin();
		while (itFrame != itSec->listaFrames.end())
		{
			itFrame->Rotate(m_rotacion);
			itFrame++;
		}
		itSec++;
	}

	
}

float SpriteAnimado::ObtenerRotacion()
{
	return m_rotacion;
}

void SpriteAnimado::VoltearX(bool volteado)
{
	m_volteadoX = volteado;
	
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	while (itSec != m_listaSecuencias.end())
	{
		std::vector<sf::Sprite>::iterator itFrame = itSec->listaFrames.begin();
		while (itFrame != itSec->listaFrames.end())
		{
			itFrame->FlipX(m_volteadoX);
			itFrame++;
		}
		itSec++;
	}
}

void SpriteAnimado::VoltearY(bool volteado)
{
	m_volteadoY = volteado;
	
	std::vector<Secuencia>::iterator itSec = m_listaSecuencias.begin();
	while (itSec != m_listaSecuencias.end())
	{
		std::vector<sf::Sprite>::iterator itFrame = itSec->listaFrames.begin();
		while (itFrame != itSec->listaFrames.end())
		{
			itFrame->FlipY(m_volteadoY);
			itFrame++;
		}
		itSec++;
	}
	
}

bool SpriteAnimado::VolteadoX()
{
	return m_volteadoX;
}

bool SpriteAnimado::VolteadoY()
{
	return m_volteadoY;
}

void SpriteAnimado::Invertir(bool invertido)
{
	m_invertido=invertido;
}

bool SpriteAnimado::Invertido()
{
	return m_invertido;
}

} // Namespace gge

